#pragma once

#include "D3D11Enum.h"
#include "DXGI.h"
#include "D3D11Interface.h"

namespace DX4WRT
{
	namespace Direct3D11
	{
		ref class Direct3D11Device : IDevice
		{
			public: 
				Direct3D11Device (ID3D11Device* device)
					: m_Device (device)
				{
				}

				~Direct3D11Device ()
				{
					if (m_Device != nullptr)
					{
						m_Device->Release ();
						m_Device = nullptr;
					}
				}

				IBuffer^ CreateBuffer (BufferDescription^ description, SubresourceData^ initialData);
				ITexture1D^ CreateTexture1D(Texture1DDescription^ description, array<SubresourceData^>^ initialData); 
				ITexture2D^ CreateTexture2D(Texture2DDescription^ description, array<SubresourceData^>^ initialData); 
				ITexture3D^ CreateTexture3D(Texture3DDescription^ description, array<SubresourceData^>^ initialData); 
				IShaderResourceView^ CreateShaderResourceView (IResource^ resource, ShaderResourceViewDescription^ description);				
				IUnorderedAccessView^ CreateUnorderedAccessView (IResource^ resource, UnorderedAccessViewDescription^ description);
				IRenderTargetView^ CreateRenderTargetView (IResource^ resource, RenderTargetViewDescription^ description);
				IDepthStencilView^ CreateDepthStencilView (IResource^ resource, DepthStencilViewDescription^ description);
				IInputLayout^ CreateInputLayout (array<InputElementDescription^>^ inputElementDescriptions, array<uint8>^shaderBytecodeWithInputSignature);
				IVertexShader^ CreateVertexShader (array<uint8>^ shaderBytecode, IClassLinkage^ classLinkage);
				IGeometryShader^ CreateGeometryShader (array<uint8>^ shaderBytecode, IClassLinkage^ classLinkage);
				IGeometryShader^ CreateGeometryShaderWithStreamOutput (array<uint8>^ shaderBytecode, array<StreamOutDeclarationEntry^>^ streamOutDeclaration, array<uint32>^ bufferStrides,  uint32 rasterizedStream, IClassLinkage^ classLinkage);
				IPixelShader^ CreatePixelShader (array<uint8>^ shaderBytecode, IClassLinkage^ classLinkage);
				IHullShader^ CreateHullShader (array<uint8>^ shaderBytecode, IClassLinkage^ classLinkage);
				IDomainShader^ CreateDomainShader (array<uint8>^ shaderBytecode, IClassLinkage^ classLinkage);
				IComputeShader^ CreateComputeShader (array<uint8>^ shaderBytecode, IClassLinkage^ classLinkage);
				IClassLinkage^ CreateClassLinkage ();
				IBlendState^ CreateBlendState (BlendDescription^ description);
				IDepthStencilState^ CreateDepthStencilState (DepthStencilDescription^ description);
				IRasterizerState^ CreateRasterizerState (RasterizerDescription^ description);
				ISamplerState^ CreateSamplerState (SamplerDescription^ description);
				IQuery^ CreateQuery (QueryDescription^ description);
				IPredicate^ CreatePredicate (QueryDescription^ description);
				ICounter^ CreateCounter (CounterDescription^ description);
				IDeviceContext^ CreateDeferredContext (uint32 contextFlags);

				uint32 CheckMultisampleQualityLevels (DX4WRT::DXGI::Format format, uint32 sampleCount);

				property DX4WRT::Direct3D::FeatureLevel FeatureLevel
				{ 
					DX4WRT::Direct3D::FeatureLevel get ()
					{	
						return (DX4WRT::Direct3D::FeatureLevel)m_Device->GetFeatureLevel();
					};
				}

				property DX4WRT::Direct3D11::DeviceCreate CreationFlags
				{
					DX4WRT::Direct3D11::DeviceCreate get ()
					{
						return (DX4WRT::Direct3D11::DeviceCreate)m_Device->GetCreationFlags();
					}
				}

				property DX4WRT::DXGI::IDevice^ DXGIDevice{ DX4WRT::DXGI::IDevice^ get();}
				property IDeviceContext^ ImmediateContext{ IDeviceContext^ get();}

			private:
				ID3D11Device* m_Device;
		};

		ref class DeviceContext: IDeviceContext
		{
			public:
				DeviceContext (ID3D11DeviceContext* pDeviceContext);
				~DeviceContext ();

				void VSSetConstantBuffers (uint32 startSlot, array<IBuffer^>^ constantBuffers);
				void PSSetShaderResources (uint32 startSlot, array<IShaderResourceView^>^ shaderResourceViews);
				void PSSetShader (IPixelShader^ pixelShader, array<IClassInstance^>^ classInstances);
				void PSSetSamplers (uint32 startSlot, array<ISamplerState^>^ samplerStates);
				void VSSetShader (IVertexShader^ vertexShader, array<IClassInstance^>^ classInstances);
				void DrawIndexed(uint32 indexCount, uint32 startIndexLocation, int32 baseVertexLocation) {m_pDeviceContext->DrawIndexed(indexCount, startIndexLocation, baseVertexLocation);}
				void Draw(uint32 indexCount, uint32 startIndexLocation) {m_pDeviceContext->Draw(indexCount, startIndexLocation);}

				void PSSetConstantBuffers (uint32 startSlot, array<IBuffer^>^ constantBuffers);
				void IASetInputLayout (IInputLayout^ inputLayout);
				void IASetVertexBuffers (uint32 startSlot, array<IBuffer^>^ vertexBuffers, array<uint32>^ strides, array<uint32>^ offsets);
				void IASetIndexBuffer (IBuffer^ indexBuffer, DX4WRT::DXGI::Format format, uint32 offset);
				void DrawIndexedInstanced(uint32 indexCountPerInstance, uint32 instanceCount, uint32 startIndexLocation, int32 baseVertexLocation, int32 startInstanceLocation) {m_pDeviceContext->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);}
				void DrawInstanced(uint32 vertexCountPerInstance,uint32 instanceCount, uint32 startVertexLocation, uint32 startInstanceLocation) {m_pDeviceContext->DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation);}
				void GSSetConstantBuffers (uint32 startSlot, array<IBuffer^>^ constantBuffers);
				void GSSetShader (IGeometryShader^ geometryShader, array<IClassInstance^>^ classInstances);
				void IASetPrimitiveTopology(PrimitiveTopology topology) {m_pDeviceContext->IASetPrimitiveTopology ((D3D11_PRIMITIVE_TOPOLOGY)topology);}
				void VSSetShaderResources (uint32 startSlot, array<IShaderResourceView^>^ shaderResourceViews);
				void VSSetSamplers (uint32 startSlot, array<ISamplerState^>^ samplerStates);
				void Begin (IAsynchronous^ async);
				void End (IAsynchronous^ async);

				void SetPredication (IPredicate^ predicate, bool predicateValue);
				void GSSetShaderResources (uint32 startSlot, array<IShaderResourceView^>^ shaderResourceViews);
				void GSSetSamplers (uint32 startSlot, array<ISamplerState^>^ samplerStates);
				void OMSetRenderTargets (array<IRenderTargetView^>^ renderTargetViews, IDepthStencilView^ depthStencilView);
				void OMSetRenderTargetsAndUnorderedAccessViews (array<IRenderTargetView^>^ renderTargetViews, IDepthStencilView^ depthStencilView, uint32 uAVStartSlot, array<IUnorderedAccessView^>^ unorderedAccessViews, array<uint32>^ uAVInitialCounts);
				void OMSetBlendState (IBlendState^ blendState, array<float>^ blendfactor, uint32 sampleMask);
				void OMSetDepthStencilState ( IDepthStencilState^ depthStencilState, uint32 stencilRef);
				void SOSetTargets (array<IBuffer^>^ targets, array<uint32>^ offsets);
				void DrawAuto () {m_pDeviceContext->DrawAuto();}
				void DrawIndexedInstancedIndirect (IBuffer^ bufferForArgs, uint32 alignedByteOffsetForArgs);
				void DrawInstancedIndirect (IBuffer^ bufferForArgs, uint32 alignedByteOffsetForArgs);
				void Dispatch (uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ) {m_pDeviceContext->Dispatch (threadGroupCountX, threadGroupCountY, threadGroupCountZ);}
				void DispatchIndirect (IBuffer^ bufferForArgs, uint32 alignedByteOffsetForArgs);
				void RSSetState (IRasterizerState^ rasterizerState);
				void RSSetViewports (array<Viewport^>^ viewports);
				void RSSetScissorRects (array<Rect^>^ rects);
				void CopySubresourceRegion (IResource^ destinationResource, uint32 destinationSubresource, uint32 destinationX, uint32 destinationY, uint32 destinationZ, IResource^ sourceResource, uint32 sourceSubresource, Box^ sourceBox);
				void CopyResource (IResource^ destinationResource, IResource^ sourceResource);
				void UpdateSubresource (IResource^ destinationResource, uint32 destinationSubresource, Box^ destinationBox, array<uint8>^ sourceData, uint32 sourceRowPitch, uint32 sourceDepthPitch);
				void CopyStructureCount (IBuffer^ destinationBuffer, uint32 destinationalignedByteOffset, IUnorderedAccessView^ sourceView);
				void ClearRenderTargetView (IRenderTargetView^ rendertTargetView, array<float>^ colorRGBA);
				void ClearUnorderedAccessViewUint (IUnorderedAccessView^ unorderedAccessView, array<uint32>^ values);
				void ClearUnorderedAccessViewFloat (IUnorderedAccessView^ unorderedAccessView, array<float>^ values);
				void ClearDepthStencilView (IDepthStencilView^ depthStencilView, Clear clear, float depth, uint8 stencil);
				void GenerateMips (IShaderResourceView^ shaderResourceView);
				void SetResourceMinLOD (IResource^ resource, float minLOD);
				float GetResourceMinLOD (IResource^ resource);
				void ResolveSubresource (IResource^ destionationResource, uint32 destinationSubresource, IResource^ sourceResource, uint32 sourceSubresource, DXGI::Format format);
				void ExecuteCommandList(ICommandList^ commandList, bool restoreContextState);
				void HSSetShaderResources (uint32 startSlot, array<IShaderResourceView^>^ shaderResourceViews);
				void HSSetShader (IHullShader^ hullShader, array<IClassInstance^>^ classInstances);
				void HSSetSamplers (uint32 startSlot, array<ISamplerState^>^ samplerStates);
				void HSSetConstantBuffers (uint32 startSlot, array<IBuffer^>^ constantBuffers);
				void DSSetShaderResources (uint32 startSlot, array<IShaderResourceView^>^ shaderResourceViews);
				void DSSetShader (IDomainShader^ domainShader, array<IClassInstance^>^ classInstances);
				void DSSetSamplers (uint32 startSlot, array<ISamplerState^>^ samplerStates);
				void DSSetConstantBuffers (uint32 startSlot, array<IBuffer^>^ constantBuffers);
				void CSSetShaderResources (uint32 startSlot, array<IShaderResourceView^>^ shaderResourceViews);
				void CSSetUnorderedAccessViews(uint32 startSlot, array<IUnorderedAccessView^>^ unorderedAccessViews, array<uint32>^ uAVInitialCounts);
				void CSSetShader (IComputeShader^ computeShader, array<IClassInstance^>^ classInstances);
				void CSSetSamplers (uint32 startSlot, array<ISamplerState^>^ samplerStates);
				void CSSetConstantBuffers (uint32 startSlot, array<IBuffer^>^ constantBuffers);

				ICommandList^ FinishCommandList (bool restoreDeferredContextState);
				void ClearState () {m_pDeviceContext->ClearState();}
				void Flush () {m_pDeviceContext->Flush();}
				property DeviceContextType Type { DeviceContextType get();}
				property uint32 ContextFlags { uint32 get();}

			internal:
				ID3D11DeviceContext* GetNative () {return m_pDeviceContext;}

			private:
				ID3D11DeviceContext* m_pDeviceContext;
		};

		ref class Resource
		{
			public:

			internal:
				virtual ID3D11Resource* GetNativeResource () = 0;
				ResourceDimension GetResourceDimenesion ();
				uint32 GetEvictionPriority ();
				void SetEvictionPriority (uint32 value);
		};

		ref class Buffer : Resource, IBuffer
		{
			public:
				Buffer (ID3D11Buffer* pBuffer);
				~Buffer ();

				property ResourceDimension ResourceType {ResourceDimension get (){return GetResourceDimenesion();}}
				property uint32 EvictionPriority {uint32 get (){return GetEvictionPriority();} void set (uint32 value){SetEvictionPriority(value);}}

				property uint32 ByteWidth {uint32 get() {UpdateDesc();return m_pDesc->ByteWidth;}}
				property DX4WRT::Direct3D11::Usage Usage {DX4WRT::Direct3D11::Usage get() {UpdateDesc();return (DX4WRT::Direct3D11::Usage)m_pDesc->Usage;}}
				property DX4WRT::Direct3D11::Bind Bind {DX4WRT::Direct3D11::Bind get() {UpdateDesc();return (DX4WRT::Direct3D11::Bind)m_pDesc->BindFlags;}}
				property DX4WRT::Direct3D11::CPUAccess CPUAccess {DX4WRT::Direct3D11::CPUAccess get() {UpdateDesc();return (DX4WRT::Direct3D11::CPUAccess)m_pDesc->CPUAccessFlags;}}
				property DX4WRT::Direct3D11::ResourceMisc Misc {DX4WRT::Direct3D11::ResourceMisc get() {UpdateDesc();return (DX4WRT::Direct3D11::ResourceMisc)m_pDesc->MiscFlags;}}
				property uint32 StructureByteStride {uint32 get() {UpdateDesc();return m_pDesc->StructureByteStride;}}

			internal:
				ID3D11Buffer* GetNative () {return m_pBuffer;}
				ID3D11Resource* GetNativeResource () {return m_pBuffer;}

			private:
				ID3D11Buffer* m_pBuffer;
				D3D11_BUFFER_DESC* m_pDesc;

				void UpdateDesc ();
		};

		ref class Texture1D : Resource, ITexture1D
		{
			public:
				Texture1D (ID3D11Texture1D* pTexture1D);
				~Texture1D ();

				property ResourceDimension ResourceType {ResourceDimension get (){return GetResourceDimenesion();}}
				property uint32 EvictionPriority {uint32 get (){return GetEvictionPriority();} void set (uint32 value){SetEvictionPriority(value);}}

				property uint32 Width {uint32 get() {UpdateDesc();return m_pDesc->Width;}}
				property uint32 MipLevels {uint32 get() {UpdateDesc();return m_pDesc->MipLevels;}}
				property uint32 ArraySize {uint32 get() {UpdateDesc();return m_pDesc->ArraySize;}}
				property DX4WRT::DXGI::Format Format {DX4WRT::DXGI::Format get() {UpdateDesc();return (DX4WRT::DXGI::Format)m_pDesc->Format;}}
				property DX4WRT::Direct3D11::Usage Usage {DX4WRT::Direct3D11::Usage get() {UpdateDesc();return (DX4WRT::Direct3D11::Usage)m_pDesc->Usage;}}
				property DX4WRT::Direct3D11::Bind Bind {DX4WRT::Direct3D11::Bind get() {UpdateDesc();return (DX4WRT::Direct3D11::Bind)m_pDesc->BindFlags;}}
				property DX4WRT::Direct3D11::CPUAccess CPUAccess {DX4WRT::Direct3D11::CPUAccess get() {UpdateDesc();return (DX4WRT::Direct3D11::CPUAccess)m_pDesc->CPUAccessFlags;}}
				property DX4WRT::Direct3D11::ResourceMisc Misc {DX4WRT::Direct3D11::ResourceMisc get() {UpdateDesc();return (DX4WRT::Direct3D11::ResourceMisc)m_pDesc->MiscFlags;}}

			internal:
				ID3D11Texture1D* GetNative () {return m_pTexture1D;}
				ID3D11Resource* GetNativeResource () {return m_pTexture1D;}

			private:
				ID3D11Texture1D* m_pTexture1D;
				D3D11_TEXTURE1D_DESC* m_pDesc;

				void UpdateDesc ();
		};

		ref class Texture2D : Resource, ITexture2D
		{
			public:
				Texture2D (ID3D11Texture2D* pTexture2D);
				~Texture2D ();

				property ResourceDimension ResourceType {ResourceDimension get (){return GetResourceDimenesion();}}
				property uint32 EvictionPriority {uint32 get (){return GetEvictionPriority();} void set (uint32 value){SetEvictionPriority(value);}}

				property uint32 Width {uint32 get() {UpdateDesc();return m_pDesc->Width;}}
				property uint32 Height {uint32 get() {UpdateDesc();return m_pDesc->Height;}}
				property uint32 MipLevels {uint32 get() {UpdateDesc();return m_pDesc->MipLevels;}}
				property uint32 ArraySize {uint32 get() {UpdateDesc();return m_pDesc->ArraySize;}}
				property DX4WRT::DXGI::Format Format {DX4WRT::DXGI::Format get() {UpdateDesc();return (DX4WRT::DXGI::Format)m_pDesc->Format;}}
				property uint32 SampleCount {uint32 get() {UpdateDesc();return m_pDesc->SampleDesc.Count;}}
				property uint32 SampleQuality {uint32 get() {UpdateDesc();return m_pDesc->SampleDesc.Quality;}}
				property DX4WRT::Direct3D11::Usage Usage {DX4WRT::Direct3D11::Usage get() {UpdateDesc();return (DX4WRT::Direct3D11::Usage)m_pDesc->Usage;}}
				property DX4WRT::Direct3D11::Bind Bind {DX4WRT::Direct3D11::Bind get() {UpdateDesc();return (DX4WRT::Direct3D11::Bind)m_pDesc->BindFlags;}}
				property DX4WRT::Direct3D11::CPUAccess CPUAccess {DX4WRT::Direct3D11::CPUAccess get() {UpdateDesc();return (DX4WRT::Direct3D11::CPUAccess)m_pDesc->CPUAccessFlags;}}
				property DX4WRT::Direct3D11::ResourceMisc Misc {DX4WRT::Direct3D11::ResourceMisc get() {UpdateDesc();return (DX4WRT::Direct3D11::ResourceMisc)m_pDesc->MiscFlags;}}

			internal:
				ID3D11Texture2D* GetNative () {return m_pTexture2D;}
				ID3D11Resource* GetNativeResource () {return m_pTexture2D;}

			private:
				ID3D11Texture2D* m_pTexture2D;
				D3D11_TEXTURE2D_DESC* m_pDesc;

				void UpdateDesc ();
		};

		ref class Texture3D : Resource, ITexture3D
		{
			public:
				Texture3D (ID3D11Texture3D* pTexture3D);
				~Texture3D ();

				property ResourceDimension ResourceType {ResourceDimension get (){return GetResourceDimenesion();}}
				property uint32 EvictionPriority {uint32 get (){return GetEvictionPriority();} void set (uint32 value){SetEvictionPriority(value);}}

				property uint32 Width {uint32 get() {UpdateDesc();return m_pDesc->Width;}}
				property uint32 Height {uint32 get() {UpdateDesc();return m_pDesc->Height;}}
				property uint32 Depth {uint32 get() {UpdateDesc();return m_pDesc->Depth;}}
				property uint32 MipLevels {uint32 get() {UpdateDesc();return m_pDesc->MipLevels;}}
				property DX4WRT::DXGI::Format Format {DX4WRT::DXGI::Format get() {UpdateDesc();return (DX4WRT::DXGI::Format)m_pDesc->Format;}}
				property DX4WRT::Direct3D11::Usage Usage {DX4WRT::Direct3D11::Usage get() {UpdateDesc();return (DX4WRT::Direct3D11::Usage)m_pDesc->Usage;}}
				property DX4WRT::Direct3D11::Bind Bind {DX4WRT::Direct3D11::Bind get() {UpdateDesc();return (DX4WRT::Direct3D11::Bind)m_pDesc->BindFlags;}}
				property DX4WRT::Direct3D11::CPUAccess CPUAccess {DX4WRT::Direct3D11::CPUAccess get() {UpdateDesc();return (DX4WRT::Direct3D11::CPUAccess)m_pDesc->CPUAccessFlags;}}
				property DX4WRT::Direct3D11::ResourceMisc Misc {DX4WRT::Direct3D11::ResourceMisc get() {UpdateDesc();return (DX4WRT::Direct3D11::ResourceMisc)m_pDesc->MiscFlags;}}

			internal:
				ID3D11Texture3D* GetNative () {return m_pTexture3D;}
				ID3D11Resource* GetNativeResource () {return m_pTexture3D;}

			private:
				ID3D11Texture3D* m_pTexture3D;
				D3D11_TEXTURE3D_DESC* m_pDesc;

				void UpdateDesc ();
		};

		ref class DepthStencilView : IDepthStencilView
		{
			public:
				DepthStencilView (ID3D11DepthStencilView* pDepthStencilView);
				~DepthStencilView ();

			internal:
				ID3D11DepthStencilView* GetNative () {return m_pDepthStencilView;}

			private:
				ID3D11DepthStencilView* m_pDepthStencilView;
		};

		ref class RenderTargetView : IRenderTargetView
		{
			public:
				RenderTargetView (ID3D11RenderTargetView* pRenderTargetView);
				~RenderTargetView ();

			internal:
				ID3D11RenderTargetView* GetNative () {return m_pRenderTargetView;}

			private:
				ID3D11RenderTargetView* m_pRenderTargetView;
		};

		ref class ShaderResourceView : IShaderResourceView
		{
			public:
				ShaderResourceView (ID3D11ShaderResourceView* pShaderResourceView);
				~ShaderResourceView ();

			internal:
				ID3D11ShaderResourceView* GetNative () {return m_pShaderResourceView;}

			private:
				ID3D11ShaderResourceView* m_pShaderResourceView;
		};

		ref class UnorderedAccessView : IUnorderedAccessView
		{
			public:
				UnorderedAccessView (ID3D11UnorderedAccessView* pUnorderedAccessView);
				~UnorderedAccessView ();

			internal:
				ID3D11UnorderedAccessView* GetNative () {return m_pUnorderedAccessView;}

			private:
				ID3D11UnorderedAccessView* m_pUnorderedAccessView;
		};

		ref class ComputeShader : IComputeShader
		{
			public:
				ComputeShader (ID3D11ComputeShader* pComputeShader);
				~ComputeShader ();

			internal:
				ID3D11ComputeShader* GetNative () {return m_pComputeShader;}

			private:
				ID3D11ComputeShader* m_pComputeShader;
		};

		ref class DomainShader : IDomainShader
		{
			public:
				DomainShader (ID3D11DomainShader* pDomainShader);
				~DomainShader ();

			internal:
				ID3D11DomainShader* GetNative () {return m_pDomainShader;}

			private:
				ID3D11DomainShader* m_pDomainShader;
		};

		ref class GeometryShader : IGeometryShader
		{
			public:
				GeometryShader (ID3D11GeometryShader* pGeometryShader);
				~GeometryShader ();

			internal:
				ID3D11GeometryShader* GetNative () {return m_pGeometryShader;}

			private:
				ID3D11GeometryShader* m_pGeometryShader;
		};

		ref class HullShader : IHullShader
		{
			public:
				HullShader (ID3D11HullShader* pHullShader);
				~HullShader ();

			internal:
				ID3D11HullShader* GetNative () {return m_pHullShader;}

			private:
				ID3D11HullShader* m_pHullShader;
		};

		ref class PixelShader : IPixelShader
		{
			public:
				PixelShader (ID3D11PixelShader* pPixelShader);
				~PixelShader ();

			internal:
				ID3D11PixelShader* GetNative () {return m_pPixelShader;}

			private:
				ID3D11PixelShader* m_pPixelShader;
		};

		ref class VertexShader : IVertexShader
		{
			public:
				VertexShader (ID3D11VertexShader* pVertexShader);
				~VertexShader ();

			internal:
				ID3D11VertexShader* GetNative () {return m_pVertexShader;}

			private:
				ID3D11VertexShader* m_pVertexShader;
		};

		ref class BlendState : IBlendState
		{
			public:
				BlendState (ID3D11BlendState* pBlendState);
				~BlendState ();

			internal:
				ID3D11BlendState* GetNative () {return m_pBlendState;}

			private:
				ID3D11BlendState* m_pBlendState;
		};

		ref class DepthStencilState : IDepthStencilState
		{
			public:
				DepthStencilState (ID3D11DepthStencilState* pDepthStencilState);
				~DepthStencilState ();

			internal:
				ID3D11DepthStencilState* GetNative () {return m_pDepthStencilState;}

			private:
				ID3D11DepthStencilState* m_pDepthStencilState;
		};

		ref class RasterizerState : IRasterizerState
		{
			public:
				RasterizerState (ID3D11RasterizerState* pRasterizerState);
				~RasterizerState ();

			internal:
				ID3D11RasterizerState* GetNative () {return m_pRasterizerState;}

			private:
				ID3D11RasterizerState* m_pRasterizerState;
		};

		ref class SamplerState : ISamplerState
		{
			public:
				SamplerState (ID3D11SamplerState* pSamplerState);
				~SamplerState ();

			internal:
				ID3D11SamplerState* GetNative () {return m_pSamplerState;}

			private:
				ID3D11SamplerState* m_pSamplerState;
		};

		ref class InputLayout : IInputLayout
		{
			public:
				InputLayout (ID3D11InputLayout* pInputLayout);
				~InputLayout ();

			internal:
				ID3D11InputLayout* GetNative () {return m_pInputLayout;}

			private:
				ID3D11InputLayout* m_pInputLayout;
		};

		ref class ClassInstance : IClassInstance
		{
			public:
				ClassInstance (ID3D11ClassInstance* pClassInstance);
				~ClassInstance ();

			internal:
				ID3D11ClassInstance* GetNative () {return m_pClassInstance;}

			private:
				ID3D11ClassInstance* m_pClassInstance;
		};

		ref class ClassLinkage : IClassLinkage
		{
			public:
				ClassLinkage (ID3D11ClassLinkage* pClassLinkage);
				~ClassLinkage ();

			internal:
				ID3D11ClassLinkage* GetNative () {return m_pClassLinkage;}

			private:
				ID3D11ClassLinkage* m_pClassLinkage;
		};

		ref class CommandList : ICommandList
		{
			public:
				CommandList (ID3D11CommandList* pCommandList);
				~CommandList ();

			internal:
				ID3D11CommandList* GetNative () {return m_pCommandList;}

			private:
				ID3D11CommandList* m_pCommandList;
		};

		ref class Asynchronous
		{
			internal:
				virtual ID3D11Asynchronous* GetNativeAsynchronous() = 0;
		};

		ref class Query : Asynchronous, IQuery
		{
			public:
				Query (ID3D11Query* pQuery);
				~Query ();

			internal:
				ID3D11Query* GetNative () {return m_pQuery;}
				virtual ID3D11Asynchronous* GetNativeAsynchronous() {return m_pQuery;}

			private:
				ID3D11Query* m_pQuery;
		};

		ref class Predicate : Asynchronous, IPredicate
		{
			public:
				Predicate (ID3D11Predicate* pPredicate);
				~Predicate ();

			internal:
				ID3D11Predicate* GetNative () {return m_pPredicate;}
				virtual ID3D11Asynchronous* GetNativeAsynchronous() {return m_pPredicate;}

			private:
				ID3D11Predicate* m_pPredicate;
		};

		ref class Counter : Asynchronous, ICounter
		{
			public:
				Counter (ID3D11Counter* pCounter);
				~Counter ();

			internal:
				ID3D11Counter* GetNative () {return m_pCounter;}
				virtual ID3D11Asynchronous* GetNativeAsynchronous() {return m_pCounter;}

			private:
				ID3D11Counter* m_pCounter;
		};

		public ref class Direct3D11 sealed 
		{
			public:
				static IDevice^ CreateDevice (DX4WRT::DXGI::IAdapter^ adapter, DX4WRT::Direct3D::DriverType driverType, DX4WRT::Direct3D11::DeviceCreate flags, array<DX4WRT::Direct3D::FeatureLevel>^ featureLevels);
				static ITexture2D^ GetSwapChainBuffer (DX4WRT::DXGI::ISwapChain^swapChain, uint32 buffer);
		};


	}
}
